const Stream = require('stream');
const url_1 = require('url');
const qs = require('querystring');
/**
 * 解析 Body.body，通过 consoumeBody.call(this) 调用，避免其它地方手动调用
 */
function consumeBody() {
  if (this.bodyUsed) {
    throw new TypeError(`body used already for: ${this.url}`);
  }
  let body = this.body;
  if (Buffer.isBuffer(body)) {
    return Promise.resolve(body);
  }
  if (body == null || !(body instanceof Stream)) {
    return Promise.resolve(Buffer.alloc(0));
  }
  // body is Stream
  return new Promise((resolve, reject) => {
    let rawData = '';
    body.on('data', (chunk) => { rawData += chunk });
    body.on('error', (err) => {
      reject(new Error(`Invalid response body while trying to fetch ${this.url}: ${err.message}`));
    });
    body.on('end', () => {
      resolve(rawData);
    });
  });
}
/**
 * Body mixin
 *
 * Ref: https://fetch.spec.whatwg.org/#body
 */
class Body {
  arrayBuffer() {
    return consumeBody.call(this).then((buf) => buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));
  }
  blob() {
    return consumeBody.call(this);
  }
  text() {
    return consumeBody.call(this).then((buf) => buf.toString());
  }
  formData() {
    return consumeBody.call(this).then((buf) => buf.toString());
  }
  json() {
    return consumeBody.call(this).then((buf) => {
      try {
        return Promise.resolve(JSON.parse(buf.toString()));
      }
      catch (err) {
        return Promise.reject(new Error(`invalid json response body reason: ${err.message}`));
      }
    });
  }
  _initBody(body) {
    this.bodyUsed = false;
    if (body == null) {
      this.body = null;
    }
    else if (body instanceof url_1.URLSearchParams) { // URLSearchParams
      this.body = Buffer.from(body.toString());
    }
    else if (body instanceof ArrayBuffer) { // ArrayBuffer
      if (ArrayBuffer.isView(body)) { // ArrayBufferView
        this.body = Buffer.from(body.buffer, body.byteOffset, body.byteLength);
      }
      else {
        this.body = Buffer.from(body);
      }
    }
    else if (Buffer.isBuffer(body) || body instanceof Stream) {
      this.body = body;
    }
    else if (typeof body === 'object') {
      this.body = Buffer.from(qs.stringify(body));
    }
    else {
      this.body = Buffer.from(String(body));
    }
  }
}

module.exports = Body;

